<?php

namespace yunj\core\control\import;

use yunj\core\builder\YunjImport;
use yunj\core\Validate;

class YunjImportRow {

    /**
     * @var YunjImport
     */
    private $import;

    /**
     * @var array
     */
    private $itemData = [];

    /**
     * @var array
     */
    private $rawItemData = [];

    /**
     * 数据行数据
     * @var array
     */
    private $data;

    public function __construct(YunjImport $import, array $itemData) {
        $this->import = $import;
        $this->rawItemData = $itemData;
        $this->itemData = $itemData;
        $this->check();
    }

    // 校验
    private function check(): void {
        // 判断sheet
        if ($this->import->isSetSheet()) {
            if (!($sheet = $this->getSheet())) {
                $this->importFail("工作簿{$sheet}错误");
                return;
            } elseif (!in_array($sheet, $this->import->getSheet())) {
                $this->importFail("工作簿{$sheet}在导入模板中不存在");
                return;
            }
        }

        // 判断cols
        $sheetCols = $this->getSheetCols();
        if (!$sheetCols) {
            $this->importFail(($sheet ? "工作簿{$sheet}" : "") . "表头[cols]未配置");
            return;
        }

        // 判断参数
        $sheet = $this->getSheet();
        $validateArgs = self::getValidateArgs($sheet, $sheetCols);
        if (!$validateArgs) {
            return;
        }
        [$rule, $field] = $validateArgs;
        if (!$rule) {
            return;
        }
        $validate = $this->import->getValidate();
        $res = data_validate($validate, $rule, $field, $this->itemData, $this->import->getId() . 'Row', true);
        if (!$res) {
            $this->importFail($validate->getFieldError());
        }
    }

    /**
     * 获取验证器验证参数
     * @param $sheet
     * @param array $sheetCols
     * @return array|array[]|mixed
     */
    private static function getValidateArgs($sheet, array $sheetCols) {
        if (!$sheetCols) {
            return [];
        }

        static $args;
        $args = $args ?: [];

        if ($sheet) {
            if ($args && isset($args[$sheet])) {
                return $args[$sheet];
            }
        } else {
            if ($args) {
                return $args;
            }
        }

        $rule = [];
        $field = [];
        foreach ($sheetCols as $ck => $cv) {
            if (!isset($cv['verify']) || !$cv['verify']) continue;
            $rule[$ck] = $cv["verify"];
            $field[$ck] = $cv['title'] ?: $ck;
        }
        $colsArgs = [$rule, $field];
        if ($sheet) {
            $args[$sheet] = $colsArgs;
        } else {
            $args = $colsArgs;
        }
        return $colsArgs;
    }

    /**
     * 判断是否可以导入
     * @return bool
     */
    public function isCanImport(): bool {
        return $this->itemData['_importStatus']['code'] === 'importing';
    }

    /**
     * 导入成功时调用
     * @param string $desc
     */
    public function importSuccess(string $desc = '导入成功'): void {
        $this->itemData['_importStatus'] = [
            'code' => 'success',
            'desc' => $desc,
        ];
    }

    /**
     * 导入失败时调用
     * @param string|array $desc
     */
    public function importFail($desc = '导入失败'): void {
        if (is_string($desc)) {
            $error = [];
        } elseif (is_array($desc)) {
            $error = $desc;
            $desc = implode(';', $error);
        }
        $this->itemData['_importStatus'] = [
            'code' => 'fail',
            'desc' => $desc,
            'error' => $error,
        ];
    }

    /**
     * 获取当前数据行工作簿
     * @return mixed
     */
    public function getSheet() {
        return $this->itemData['_sheet'];
    }

    /**
     * 获取当前数据行工作簿表头
     * @return array
     */
    public function getSheetCols(): array {
        return $this->import->getCols($this->getSheet());
    }

    /**
     * 获取当前数据行数据
     * @return array
     */
    public function getData(): array {
        if (is_null($this->data)) {
            $data = [];
            $cols = $this->getSheetCols();
            if ($cols) {
                $dataKeys = array_keys($cols);
                foreach ($dataKeys as $key) {
                    if (array_key_exists($key, $this->itemData)) {
                        $data[$key] = $this->itemData[$key];
                    }
                }
            }
            $this->data = $data;
        }
        return $this->data;
    }

    /**
     * 响应数据
     * @return array
     */
    public function responseData(): array {
        $rawItemData = $this->rawItemData;
        $rawItemData['_importStatus'] = $this->itemData['_importStatus'];
        return $rawItemData;
    }

    // 调用不存在属性时
    public function __get($name) {
        return $this->itemData[$name] ?? null;
    }

}